package com.example.springbootsecurity.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

/**
 * 配置Spring Security的类
 * 定义了项目的安全策略，包括请求的授权规则、登录配置和注销配置
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    /**
     * 配置SecurityFilterChain bean的方法
     * 定义了HTTP请求的安全约束，包括哪些URL模式需要公开访问，哪些需要身份验证，以及登录和注销的配置
     *
     * @param http 用于配置Web安全的HttpSecurity对象
     * @return 配置好的SecurityFilterChain对象
     * @throws Exception 如果配置过程中发生错误
     */
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                // 配置请求的授权规则
                .authorizeHttpRequests(auth -> auth
                        // 允许所有人访问根路径和登录路径
                        .requestMatchers("/", "/login").permitAll()
                        // 访问/home路径需要身份验证
                        .requestMatchers("/home").authenticated()
                        // 访问/admin路径需要ADMIN角色
                        .requestMatchers("/admin").hasRole("ADMIN")
                        // 其他所有请求都需要身份验证
                        .anyRequest().authenticated()
                )
                // 配置登录页面和成功登录后的行为
                .formLogin(form -> form
                        // 自定义登录页面路径
                        .loginPage("/login")
                        // 登录成功后默认跳转到/home路径
                        .defaultSuccessUrl("/home", true)
                        // 允许所有人访问登录页面
                        .permitAll()
                )
                // 配置注销行为
                .logout(logout -> logout
                        // 注销成功后跳转到根路径
                        .logoutSuccessUrl("/")
                        // 允许所有人访问注销
                        .permitAll()
                )
                // 添加密码管理配置
                // .passwordManagement(Customizer.withDefaults())
                .passwordManagement((management) -> management
                        .changePasswordPage("/update-password"));
        // 构建并返回配置好的SecurityFilterChain对象
        return http.build();
    }

    /**
     * 配置UserDetailsService bean的方法
     * 在内存中创建并管理用户账户，用于身份验证
     *
     * @return InMemoryUserDetailsManager对象，管理内存中的用户详情
     */
    @Bean
    public UserDetailsService userDetailsService() {
        User.UserBuilder userBuilder = User.withDefaultPasswordEncoder();
        // 创建一个普通用户的UserDetails对象
        UserDetails user = userBuilder
                .username("user")
                .password("password")
                .roles("USER")
                .build();
        System.out.println(user.getPassword());

        // 创建一个管理员用户的UserDetails对象
        UserDetails admin = userBuilder
                .username("admin")
                .password("password")
                .roles("ADMIN")
                .build();

        // 返回一个内存用户详情管理器，管理上述两个用户
        return new InMemoryUserDetailsManager(user, admin);
    }

    /**
     * 创建并返回一个SecurityEvaluationContextExtension实例。
     * 这个扩展用于在Spring Security的表达式求值上下文中添加安全相关功能。
     *
     * @return 配置好的SecurityEvaluationContextExtension实例
     */
    @Bean
    public SecurityEvaluationContextExtension securityEvaluationContextExtension() {
        return new SecurityEvaluationContextExtension();
    }

}